package com.fang.gittest;

import org.apache.commons.io.FileUtils;

import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.*;
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 文件解析器,用来实现对文件的解析
 */
public class FileParse {


    public static final String PATH_TEST = "src/test/java/";

    public static final String PATH_MAIN = "src/main/java/";

    public static final String SUBFIX_JAVA = ".java";

    public static final String TEST_SUBFIX_JAVA = "Test.java";

    public static final String NAME_TEST = "test";

    public static final String WHITE_SPACE = " ";

    public static final String SUBFIX_XML = ".xml";

    public static final String EMPTY_SIGN = "";

    public static final String SIGN_LEFT_BRACES = "(";


    public static final String NAME_COM = "com";

    public static final String PATTERN_METHOD_DECLARE = "(private |public |protected ).*\\w[a-z]*\\(*\\)";

    public static final String START_METHOD = "public static void main";


    /**
     * 通过git 提交的数据解析出对应的文件列表
     *
     * @param path
     * @return
     */
    public List<String> getGitStatusNotDelFileList(String path) {
        String[] paths = path.split("\\n");
        List<String> pathList = Arrays.asList(paths);

        if (pathList.size() > 0) {
            pathList = pathList.subList(0, pathList.size() - 1);
        }
        return pathList.stream().filter(s -> !s.contains(SUBFIX_XML)).map(item -> {
            String newPath = item;
            //消除掉tag
            int index = item.indexOf(SUBFIX_JAVA);
            int startIndex = item.indexOf(NAME_COM);
            if (index != -1) {
                newPath = item.substring(startIndex, index + 5);
            }
            return newPath;
        }).collect(Collectors.toList());


    }

    /**
     * 从文件中找到JAVA方法的签名
     *
     * @param path
     * @return
     */
    public List<String> getMethodForFile(String path) {
        List<String> methodList = new ArrayList<>();
        File file = new File(path);
        if (!file.exists()) {
            return methodList;
        }
        try {
            String content = FileUtils.readFileToString(file, Charset.defaultCharset());
            methodList = parseJavaMethod(content);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return methodList;
    }


    /**
     * 从与之对应的测试中匹配对应的方法签名
     *
     * @param path 类的路劲
     * @return 返回没有匹配的 test方法
     */
    public Set<String> matchTestMethod(String path) {
        //获得测试的路径
        String testPath = PATH_TEST + path;
        //资源的路径
        String resourcePath = PATH_MAIN + path;
        //对应类的方法声明
        List<String> resoucesMethod = getMethodForFile(resourcePath);
        //过滤主启动方法
        resoucesMethod = resoucesMethod.stream().filter(s -> !s.contains(START_METHOD)).collect(Collectors.toList());

        //对应测试方法的声明
        String testClassName = testPath.replace(SUBFIX_JAVA, TEST_SUBFIX_JAVA);
        final List<String> testMethod = getMethodForFile(testClassName);

        Set<String> noMatchMethod = null;
        noMatchMethod = resoucesMethod.stream().filter(methodSign -> {
            for (int i = 0; i < testMethod.size(); i++) {
                String testMethodSign = testMethod.get(i);
                if (testMethodMatchMethod(methodSign, testMethodSign)) {
                    return false;
                }
            }
            return true;
        }).collect(Collectors.toSet());
        return noMatchMethod;
    }


    /**
     * 测试方案和 普通方法的匹配关系
     *
     * @param method
     * @return
     */
    public boolean testMethodMatchMethod(String method, String testMethod) {
        //获得方法的方法名称
        return getMethodName(method).equals(testMethodToMethod(testMethod));
    }


    /**
     * 测试方法转换为 普通方法的实现
     *
     * @param testMethod
     * @return
     */
    public String testMethodToMethod(String testMethod) {
        String name = testMethod.replace(NAME_TEST, EMPTY_SIGN);
        String methodName = getMethodName(name);
        return methodName.substring(0, 1).toLowerCase() + methodName.substring(1);
    }

    /**
     * 获得一个方法的方法名称
     *
     * @param method
     * @return
     */
    public String getMethodName(String method) {

        int paramStartIndex = method.indexOf(SIGN_LEFT_BRACES);

        String methodTemp = method.substring(0, paramStartIndex);
        method = methodTemp.substring(methodTemp.lastIndexOf(WHITE_SPACE) + 1);

        return method;
    }


    /**
     * 从一个string文本中匹配一个 方法
     *
     * @param content 文件的内容
     */
    public List<String> parseJavaMethod(String content) {

        //public,private,protected,默认 开头
        //空格
        //返回值
        //空格
        //方法名称
        //左括号
        //方法参数
        //右括号
        //空格
        //{
        Pattern pattern = Pattern.compile(PATTERN_METHOD_DECLARE);
        Matcher matcher = pattern.matcher(content);
        List<String> result = new ArrayList<>();
        while (matcher.find()) {
            String methodName = matcher.group();
            result.add(methodName);
        }
        return result;
    }

}
